// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.core;

/**
 * 任意大的整数。
 *
 * **注意：**当编译为JavaScript时，整型会被实现成JavaScript中的Number
 * （JavaScript中的所有Number都是双精度浮点数），因此限制为53位有效位。
 * 也是如此，[int]中运算符和方法的行为，
 * 在Dart VM和Dart代码编译成的JavaScript之间也有所不同。
 *
 * 当试图继承或实现int类的时候，会产生一个编译时错误。
 */
abstract class int extends num {
  /**
   * 返回环境声明变量[name]的整数值。
   *
   * 结果与下面表达式的返回值相同：
   *
   *     int.parse(const String.fromEnvironment(name, defaultValue: ""),
   *               (_) => defaultValue)
   *
   * 例子：
   *
   *     const int.fromEnvironment("defaultPort", defaultValue: 80)
   */
  external const factory int.fromEnvironment(String name, {int defaultValue});

  /**
   * 按位与运算符。
   *
   * 将`this`和[other]作为足够大的整数的两个组成部分来处理，
   * 结果是一个数值，各个位设置为`this`与[other]的值。
   *
   * 如果两个操作数都是负数，那么结果也是负数。否则，为非负数。
   */
  int operator &(int other);

  /**
   * 按位或运算符。
   *
   * 将`this`和[other]作为足够大的整数的两个组成部分来处理，
   * 结果是一个数值，各个位设置为`this`或[other]的值。
   *
   * 如果两个操作数都是非负数，那么结果也是非负数。否则，为负数。
   */
  int operator |(int other);

  /**
   * 按位异或运算符。
   *
   * 将`this`和[other]作为足够大的整数的两个组成部分来处理，
   * 结果是一个数值，各个位设置为`this`异或[other]的值。
   *
   * 如果两个操作数符号相同，结果是非负数。否则，结果为负数。
   */
  int operator ^(int other);

  /**
   * 按位取反（非）运算符。
   *
   * 将`this`作为足够大的整数的两个组成部分来处理，
   * 结果是一个数值，按位取反。
   *
   * 它将任何整数`x`映射为`-x - 1`。
   */
  int operator ~();

  /**
   * 按位左移运算符，[shiftAmount]为位移量。
   *
   * 左移运算使数值变得更大，实际上等同乘以数值`pow(2, shiftIndex)`（C/C++中用于求指数幂的函数）。
   * 也就是说，等于`this`乘以2^shift，左移3位相当于乘以8（2^3）。
   *
   * 对于结果的大小并没有限制。它可能和限制中间值
   * (使用与运算符和恰当的位掩码)相关联。
   *
   * 如果[shiftAmount]是负数，抛出错误。
   */
  int operator <<(int shiftAmount);

  /**
   * 按位右移运算符，[shiftAmount]为位移量。
   *
   * 右移运算使数值变得更小，并且舍弃最低有效位，
   * 实际上等同除以数值`pow(2, shiftIndex)`（C/C++中用于求指数幂的函数）。
   * 也就是说，等于`this`除以2^shift，右移3位相当于除以8（2^3）。
   *
   * 如果[shiftAmount]是负数，抛出错误。
   */
  int operator >>(int shiftAmount);

  /**
   * 指数求模，返回值为：`this^exponet % modulus`。
   *
   * 指数[exponent]必须是非负数，模数[modulus]必须是整数。
   */
  int modPow(int exponent, int modulus);

  /**
   * 分数求模（乘法逆元），返回值为：`this^-1 % modulus`。
   *
   * 模数[modulus]必须是正数。
   *
   * 如果模的逆元不存在，抛出错误。
   */
  int modInverse(int modulus);

  /**
   * 返回`this`和[other]的最大公约数。
   *
   * 如果其中一个数非零，计算结果时，`this`和`other`之间数值大的整数为被除数。
   *
   * 最大公约数与顺序无关，因此`x.gcd(y)`和`y.gcd(x)`结果相同。
   *
   * 对于任何整数`x`，`x.gcd(x)`等于`x.abs()`。
   *
   * 如果`this`和`other`两个数都为零，那么结果也为零。
   */
  int gcd(int other);

  /** 当且仅当`this`是偶数时，返回true。 */
  bool get isEven;

  /** 当且仅当`this`是奇数时，返回true。 */
  bool get isOdd;

  //TODO
  
  /**
   * 返回用二进制存储`this`整数所需的最小bit数。
   *
   * bit数并不包括符号位，对于非负数（无符号），返回正常长度。
   * 对于负数，返回第一个不同于符号位的bit的位置。
   *
   * To find the number of bits needed to store the value as a signed value,
   * add one, i.e. use `x.bitLength + 1`.
   *
   *      x.bitLength == (-x-1).bitLength
   *
   *      3.bitLength == 2;     // 00000011
   *      2.bitLength == 2;     // 00000010
   *      1.bitLength == 1;     // 00000001
   *      0.bitLength == 0;     // 00000000
   *      (-1).bitLength == 0;  // 11111111
   *      (-2).bitLength == 1;  // 11111110
   *      (-3).bitLength == 2;  // 11111101
   *      (-4).bitLength == 2;  // 11111100
   */
  int get bitLength;

  /**
   * 返回`this`最小有效[width]位所表示的非负（无符号）整数，其中高于[width]的bit位全部设置成0。
   * 当所有有效bit位都高于[width]的时候，返回零。
   *
   *     (-1).toUnsigned(5) == 31   // 11111111  ->  00011111
   *
   * 该操作可以用来模拟低级语言的算术。例如，8bit的无符号数递增：
   *
   *     q = (q + 1).toUnsigned(8);
   *
   * `q`将从`0`计算到`255`，然后再回到`0`。
   *
   * 如果输入的[width]在实际位宽范围内，没有被截断，结果不变。
   * 为了保证值不变，最小宽度应该避免`x`被截断。
   * 也就是说，位宽应等于`x.bitLength`。
   *
   *     x == x.toUnsigned(x.bitLength);
   */
  int toUnsigned(int width);

  /**
   * 返回`this`最小有效[width]位，
   * 其中高于[width]的bit位扩展为符号，全部设置成[width]位置的bit值。
   *
   *                                    V--sign bit-V
   *     16.toSigned(5) == -16   //  00010000 -> 11110000
   *     239.toSigned(5) == 15   //  11101111 -> 00001111
   *                                    ^           ^
   * 该操作可以用来模拟低级语言的算术。例如，8bit的有符号数递增：
   *
   *     q = (q + 1).toSigned(8);
   *
   * `q`将从`0`计算到`127`，然后回到`-128`，再计算回`127`。
   *
   * 如果输入的[width]在实际位宽范围内，没有被截断，结果不变。
   * 为了保证值不变，最小宽度应该避免`x`被截断。
   * 也就是说，位宽应等于`x.bitLength + 1`。
   *
   *     x == x.toSigned(x.bitLength + 1);
   */
  int toSigned(int width);

  /**
   * 负值运算符。
   *
   * 对一个整数求负后，符号相反，除了零（负值也是它自身）。
   */
  int operator -();

  /**
   * 返回[int]的绝对值。
   *
   * 对于任何整数`x`，结果与`x < 0 ? -x : x`相同。
   */
  int abs();

  /**
   * 返回整数的符号。
   *
   * * 如果数值小于0，返回-1
   * * 如果数值大于0，返回1
   * * 如果数值等于0，返回0
   */
  int get sign;

  /** 返回`this`。 */
  int round();

  /** 返回`this`。 */
  int floor();

  /** 返回`this`。 */
  int ceil();

  /** 返回`this`。 */
  int truncate();

  /** 返回`this.toDouble()`。 */
  double roundToDouble();

  /** 返回`this.toDouble()`。 */
  double floorToDouble();

  /** 返回`this.toDouble()`。 */
  double ceilToDouble();

  /** 返回`this.toDouble()`。 */
  double truncateToDouble();

  /**
   * 返回一个表示`this`整数的字符串。
   *
   * 返回的字符串对于[parse]是可解析的。
   * 对于任意的`int` [:i:]，可以保证[:i == int.parse(i.toString()):]。
   */
  String toString();

  /**
   * 将[this]转换为用指定基数（进制）[radix]表示的字符串。
   *
   * 在字符串中，小写字母用于'9'以上的数字，使用'a'是10，'z'是35。
   *
   * 参数[radix]必须是2-36范围内的整数。
   */
  String toRadixString(int radix);

  /**
   * 将[source]作为一个可能有符号的整数值来解析，并返回值。
   *
   * [source]必须是一个基数（进制）为[radix]的非空序列，前缀正负号（'-'或'+'）可选。
   *
   * 参数[radix]必须是2-36范围内的整数。
   * 小写字母用于'9'以上的数字，'a'..'z'的值是10..35，大写字母和对应小写字母的值相同。
   *
   * 如果未设置参数[radix]，默认值是10。
   * 在这种情况下，[source]还可能以`0x`开头。这时，数字被解释为16进制值。
   * 实际上，这意味着`0x`被忽略，[radix]被设置为16。
   *
   * 对于任意的整数[:n:]和基数[:r:]，可以保证[:n == int.parse(n.toRadixString(r), radix: r):]。
   *
   * 如果[source]不是一个有效的整数值，那么会使用[source]作为参数调用[onError]，
   * 并且将它的返回值作为解析的结果。
   * 如果没有设置[onError]，会抛出异常[FormatException]。
   *
   * [onError]函数可以选择返回`null`。
   * 这比抛出异常，然后立即捕获[FormatException]的方式更好。
   * 例如：
   *
   *     var value = int.parse(text, onError: (source) => null);
   *     if (value == null) ... handle the problem
   *
   * [onError]函数仅在[source]类型为[String]时被调用。
   * 例如，如果[source]是`null`，那么函数不会被调用。
   */
  external static int parse(String source,
                            { int radix,
                              int onError(String source) });
}
